Passed
Branchmaster (e18bdd)
by Plamen
01:42
created

table.singleton.js ➔ ... ➔ BuildRequest   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 56
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 42
c 1
b 0
f 0
nc 4
nop 3
dl 0
loc 56
rs 8.872

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
// https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript
2
var TableSingleton = (function(){
3
    // Instance stores a reference to the Singleton
4
    var instance;
5
    function initInstance(){
6
        // Singleton
7
        // Private methods and variables
8
        function getParent(obj, objType){
9
            while(obj && obj.tagName !== objType.toUpperCase()){
10
                obj = obj.parentNode;
11
            }
12
            return obj;
13
        }
14
        function BuildRequest(rq, crntTableId, skipPropertyArray){
15
            function checkSkip(skipProperty){
16
                var result = false;
17
                if(skipPropertyArray && Object.prototype.toString
18
                        .call(skipPropertyArray) === '[object Array]'
19
                ){
20
                    if(skipPropertyArray.indexOf(skipProperty) >= 0){
21
                        result = true;
22
                    }
23
                }
24
                return result;
25
            };
26
            function getSort(){
27
                var thTags = document.getElementById(crntTableId)
28
                        .getElementsByTagName("thead")[0]
29
                        .getElementsByTagName("th");
30
                var length = thTags.length;
31
                for(var i = 0; i < length; i++){
32
                    var link = thTags[i].getElementsByTagName("a")[0];
33
                    if(link){
34
                        var span = link.getElementsByTagName("span")[0];
35
                        if(span && setSortByFirstLinkFirstSpan(span, i)){
36
                            break;
37
                        }
38
                    }
39
                }
40
            };
41
            function setSortByFirstLinkFirstSpan(span, i){
42
                var order = span.innerHTML;
43
                if(order.length === 1){
44
                    rq.colNo = i;
45
                    rq.colOrd = order === instance.strDesc ? "desc" : "asc";
46
                }
47
                return rq.colNo === i;
48
            };
49
            function getFilter(){
50
                var r = getFilterFieldsByTableID(crntTableId);
51
                if(r.filter !== null){
52
                    rq.filter = r.filter;
53
                }
54
                if(r.filterBy !== null){
55
                    rq.filterBy = r.filterBy;
56
                }
57
            };
58
59
            //Build request object
60
            if(!checkSkip("sort")){
61
                getSort();
62
            }
63
            if(!checkSkip("filter")){
64
                getFilter();
65
            }
66
67
            rq.tableId = crntTableId;
68
            return rq;
69
        }
70
        function getFilterFieldsByTableID(tableID){
71
            var fields = {filterBy: null, filter: null};
72
            var filterDiv = getFilterDivByTableIDOrNull(tableID);
73
            if(filterDiv !== null){
74
                setFilterFields(fields, filterDiv);
75
            }
76
            return fields;
77
        }
78
        function getFilterDivByTableIDOrNull(tableID){
79
            var res = null;
80
            if(document.getElementById(tableID).parentNode.getElementsByTagName("div").length > 0){
81
                for(var i = 0; i < document.getElementById(tableID).parentNode.getElementsByTagName("div").length; i++){
82
                    if(document.getElementById(tableID).parentNode.getElementsByTagName("div")[i].getAttribute("class") === "filter"){
83
                        return document.getElementById(tableID).parentNode.getElementsByTagName("div")[i];
84
                    }
85
                }
86
87
            }
88
            return res;
89
        }
90
        function setFilterFields(fields, filterDiv){
91
            var slctObj = filterDiv.getElementsByTagName("select")[0];
92
            if(slctObj && slctObj.options[slctObj.selectedIndex].value !== "all"){
93
                fields.filterBy = slctObj.options[slctObj.selectedIndex].value;
94
            }
95
            var textObj = filterDiv.getElementsByTagName("input")[0];
96
            if(textObj && textObj.value && textObj.value.length !== 0){
97
                fields.filter = encodeURIComponent(textObj.value.trim());
98
            }
99
        }
100
        function FilterGetTableId(field){
101
            if(field.tagName.toLowerCase() !== "select"){
102
                return field.getAttribute("data-table-id");
103
            }
104
            var f = field.parentNode.parentNode.getElementsByTagName("input")[0];
105
            return '' === f.value ? null : f.getAttribute("data-table-id");
106
        }
107
        var tail = [];
108
        function LoadData(tableContainer, rq){
109
            instance.setVisability(tableContainer, false);
110
            if(window.XMLHttpRequest){
111
                xmlhttp = new XMLHttpRequest();/* code for IE7+, Firefox, Chrome, Opera, Safari */
0 ignored issues
show
Bug introduced by
The variable xmlhttp seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.xmlhttp.
Loading history...
112
            }else{ 
113
                xmlhttp = new window.ActiveXObject("Microsoft.XMLHTTP");/*code for IE6, IE5 */
114
            }
115
            for(var i = 0; i < tail.length; i++){
116
                var ex_xmlhttp = tail.shift();
117
                ex_xmlhttp.abort();
118
            }
119
            xmlhttp.onreadystatechange = function(){
120
                if(xmlhttp.readyState === 4 && xmlhttp.status === 200){
121
                    var d = JSON.parse(xmlhttp.responseText);
122
                    table.DrawSection(tableContainer, d.body);
123
                    table.DrawSection(tableContainer, d.footer, "tfoot");
124
                    table.LoadEndCalback(tableContainer);
125
                    table.setVisability(tableContainer, true);
126
                    if(typeof rq === "object"){
127
                        var hover = document.getElementById(rq.tableId)
128
                                    .getElementsByTagName("th")[rq.colNo].lang;
129
                        if(hover){
130
                            table.ColumnHover(tableContainer, rq.colNo);
131
                        }
132
                    }
133
                }
134
            };
135
            xmlhttp.open("GET", RequestToUrl(rq), true);
136
            xmlhttp.send();
137
            tail.push(xmlhttp); //put at tail to can abort later any previous
138
        }
139
        function RequestToUrl(rq){
140
            var url = location.pathname + ".json" + location.search;
141
            if(typeof rq === "object"){
142
                var getUrlVarName = {
143
                    colNo: "col", colOrd: "ord", filter: "filter",
144
                    filterBy: "filter-by", pageNo: "pg", exportType: "export",
145
                    tableId: "table-id"
146
                };
147
                var flagFirst = location.search.length < 1 ? true : false;
148
                for(var r in rq){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
149
                    var clue = flagFirst === true ? "?" : "&";
150
                    url += clue + getUrlVarName[r] + "=" + rq[r];
151
                    flagFirst = false;
152
                }
153
            }
154
            return url;
155
        }
156
        function columnHoverRelease(rows, upto){
157
            for(var i = 0; i < upto; i++){
158
                for(var j = 0; j < rows[i].cells.length; j++){
159
                    if(rows[i].cells[j].lang){
160
                        rows[i].cells[j].removeAttribute("lang");
161
                    }
162
                }
163
            }
164
        }
165
        function clearSection(tSection){
166
            if(iePrior(9)){
167
                if(tSection.firstChild){
168
                    while(tSection.firstChild){
169
                        tSection.removeChild(tSection.firstChild);
170
                    }
171
                }
172
            }else{
173
                tSection.innerHTML = "";
174
            }
175
        }
176
        function iePrior(v){
177
            var rv = false;
178
            if(window.navigator.appName === 'Microsoft Internet Explorer'){
179
                var ua = window.navigator.userAgent;
180
                var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
181
                if(re.exec(ua) !== null){
182
                    rv = parseFloat(RegExp.$1);
183
                }
184
                rv = rv < v ? true : false;
185
            }
186
            return rv;
187
        }
188
        function setPagingLinksSetActions(tContainer){
189
            var pLinks = tContainer.querySelectorAll("tfoot .paging a");
190
            if(pLinks.length > 0){
191
                for(var j = 0; j < pLinks.length; j++){
192
                    pLinks[j].setAttribute("href", "javascript:void(0);");
193
                    pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
194
                }
195
            }
196
        }
197
        function footerProcessPaginationLinks(tSection){
198
            var pLinks = tSection.querySelectorAll(".paging a");
199
            if(pLinks.length > 0){
200
                for(var j = 0; j < pLinks.length; j++){
201
                    pLinks[j].setAttribute("href", "javascript:void(0);");
202
                    pLinks[j].setAttribute("onclick", "return table.GoPage(this);");
203
                }
204
            }
205
        }
206
        function SetTheTableColumnsHoverEffect(tableContainer){
207
            if(iePrior(9)){
208
                return;
209
            }
210
            var tContainer = document.getElementById(tableContainer);
211
            var tHcells = tContainer.rows[0].cells;
212
            for(var i = 0; i < tHcells.length; i++){
213
                if(tHcells[i].firstChild.tagName === "A"){
214
                    tHcells[i].firstChild.setAttribute("onmouseover", "table.ColumnHover('" + tableContainer + "'," + i + ");");
215
                    tHcells[i].firstChild.setAttribute("onmouseout", "table.ColumnHover('" + tableContainer + "');");
216
                }
217
            }
218
            setPagingLinksSetActions(tContainer);
219
        }
220
        
221
        return {
222
            rq: null,
223
            strAsc: String.fromCharCode(9650), //&#9650;
224
            strDesc: String.fromCharCode(9660),//&#9660; 
225
            ReloadData: function(tableId){
226
                var request = {};
227
                BuildRequest(request, tableId);
228
                LoadData(tableId, request);
229
            },
230
            Filter: function(field){
231
                var crntTableId = FilterGetTableId(field);
232
                if(crntTableId !== null){
233
                    var request = {};
234
                    var exRq = this.rq;
235
                    BuildRequest(request, crntTableId);
236
                    if(exRq === null ||
237
                        request.filter !== exRq.filter ||
238
                        request.filterBy !== exRq.filterBy
239
                    ){
240
                        LoadData(crntTableId, request);
241
                    }
242
                }
243
            },
244
            GoPage: function(lnk){
245
                var request = {};
246
                var table = getParent(lnk, "table");
247
                var crntTableId = table.getAttribute("id");
248
                BuildRequest(request, crntTableId);
249
                //check & serve pagination jump links
250
                var jumpDir = lnk.innerHTML.trim().substr(0, 1);
251
                if(jumpDir === "+" || jumpDir === "-"){
252
                    var current = table.querySelector("tfoot .paging .a").innerHTML;
253
                    var jump = lnk.innerHTML.replace("K", "000").replace("M", "000000000");
254
                    var jumpPage = (parseInt(current) + parseInt(jump));
255
                    lnk.parentNode.setAttribute("data-page", jumpPage);
256
                    lnk.style.transform = "none";
257
                }
258
                request.pageNo = lnk.parentNode.hasAttribute("data-page") ?
259
                                    lnk.parentNode.getAttribute("data-page") :
260
                                    lnk.innerHTML;
261
                LoadData(crntTableId, request);
262
                return false;
263
            },
264
            Export: function(lnk, eType){
265
                var request = {};
266
                var crntTableId = getParent(lnk, "table").getAttribute("id");
267
                BuildRequest(request, crntTableId);
268
                request.exportType = ["CSV", "Excel"].indexOf(eType) >= 0 ?
269
                                        eType : 
270
                                        "csv";
271
                window.open(RequestToUrl(request));
272
                return false;
273
            },
274
            Sort: function(colNo, lnk){
275
                var request = {};
276
                var crntTableId = getParent(lnk, "table").getAttribute("id");
277
                BuildRequest(request, crntTableId);
278
                if(Math.round(colNo) === request.colNo){
279
                    request.colOrd = (request.colOrd === "asc" ? "desc" : "asc");
280
                }else{
281
                    request.colNo = Math.round(colNo);
282
                    request.colOrd = "asc";
283
                }
284
                LoadData(crntTableId, request);
285
                /* Clear and add new sort arrow */
286
                var headSpans = getParent(lnk, "thead").getElementsByTagName("span");
287
                var length = headSpans.length;
288
                for(var i = 0; i < length; i++){
289
                    headSpans[i].innerHTML = "";
290
                }
291
                lnk.getElementsByTagName("span")[0].innerHTML = (request.colOrd === "desc" ? this.strDesc : this.strAsc);
292
            },
293
            DrawSection: function(tableContainer, dt, tSection){
294
                var section = tSection === "tfoot" ? "tfoot" : "tbody";
295
                tSection = document.getElementById(tableContainer).
296
                            getElementsByTagName(section)[0];
297
                clearSection(tSection);
298
                for(var i = 0; i < dt.length; i++){
299
                    var row = dt[i];
300
                    var tRow = document.createElement("tr");
301
302
                    this.DrawRow(row, tRow);
303
304
                    tSection.appendChild(tRow);
305
                    if(section === "tfoot"){
306
                        footerProcessPaginationLinks(tSection);
307
                    }
308
                    this.AppendRowCalback(tableContainer);
309
                }
310
            },
311
            DrawRow: function(row, tRow){
312
                for(var cell in row){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
313
                    var tCell = document.createElement("td");
314
                    if(typeof row[cell] === "string" || typeof row[cell] === "number"){
315
                        tCell.innerHTML = row[cell];
316
                    }else if(typeof row[cell] === "object"){
317
                        this.DrawCellFromObject(row, cell, tCell);
318
                    }
319
                    tRow.appendChild(tCell);
320
                }
321
            },
322
            DrawCellFromObject: function(row, cell, tCell){
323
                for(var attr in row[cell]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
324
                    if(typeof row[cell][attr] === "string"){
325
                        tCell.innerHTML = row[cell][attr];
326
                    }else if(typeof row[cell][attr] === "object"){
327
                        for(var v in row[cell][attr]){
1 ignored issue
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
328
                            tCell.setAttribute(v, row[cell][attr][v]);
329
                        }
330
                    }
331
                }
332
            },
333
            ColumnHover: function(tableContainer, index){
334
                if(!iePrior(9)){
335
                    var rows = document.getElementById(tableContainer).rows;
336
                    var upto = rows.length - 1;
337
                    if(typeof index === "undefined"){
338
                        columnHoverRelease(rows, upto);
339
                    } else {
340
                        for(var i = 0; i < upto; i++){
341
                            rows[i].cells[index].setAttribute("lang", "col-hover");
342
                        }
343
                    }
344
                }
345
            },
346
            setVisability: function(tableContainer, rq){
347
                var tbl = document.getElementById(tableContainer);
348
                if(rq === true){
349
                    tbl.style.filter = "none";
350
                    tbl.style.opacity = "1";
351
                    tbl.style.cursor = "auto";
352
                }else if(rq === false){
353
                    tbl.style.filter = "blur(1px)";
354
                    tbl.style.opacity = "0.8";
355
                    tbl.style.cursor = "wait";
356
                }else{
357
                    console.error("table error in the rq value");
358
                }
359
            },
360
            init: function(tableId){
361
                SetTheTableColumnsHoverEffect(tableId);
362
            },
363
            LoadEndCalback: function(tableId){
364
                if(tableId){/*Allows override*/
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
365
                }
366
            },
367
            AppendRowCalback: function(tableId){
368
                if(tableId){/*Allows override*/
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
369
                }
370
            }
371
            // - - - Imported end - - -
372
        };
373
    }
374
    return {
375
        //Get the Singleton instance if one exists, or create one if it doesn't
376
        getInstance: function(){
377
            if(!instance){
378
                instance = initInstance();
379
            }
380
            return instance;
381
        }
382
    };
383
})();
384
var table = TableSingleton.getInstance();
385